﻿using System;
using System.ComponentModel.Composition;
using Cubicle.Core.Interfaces;
using Cubicle.Core.Processors.Parameter;

namespace Cubicle.Core.Processors.Construct
{
    [Export("Cubicle.Processors.Construct.ArrayConstructProcessor", typeof(IProcessor<InstructionRequest>))]
    [ExportMetadata("Name", "ArrayConstructProcessor")]
    [ExportMetadata("Description", "Custom Construct Processor: Creates an array")]
    public class ArrayConstructProcessor : InstructionRequestProcessor
    {
        [Import]
        private ParameterProcessor _parameterProcessor;

        [ImportingConstructor]
        public ArrayConstructProcessor() : base(RequestType.CustomConstruct) { }

        #region Overrides of Processor<InstructionRequest>

        public override bool Condition(InstructionRequest request)
        {
            return base.Condition(request) 
                   && request.TargetType != null
                   && request.TargetType.IsArray 
                   && request.TargetType.GetArrayRank() == 1
                   && !request.TargetType.GetElementType().IsArray;
        }

        public override InstructionRequest ConditionalProcess(InstructionRequest request)
        {
            var elementType = request.TargetType.GetElementType();
            var parameters = request.Inst.Parameters;
            Array result;
            if (parameters == null)
            {
                result = Array.CreateInstance(elementType, 0);
            }
            else
            {
                result = Array.CreateInstance(elementType, parameters.Length);
                for (int i = 0; i < result.Length; i++)
                {
                    var parRequest = new ParameterRequest(elementType, parameters[i]);
                    _parameterProcessor.Process(parRequest);
                    result.SetValue(parRequest.Result, i);
                }
            }
            request.Complete(result);
            return request;
        }

        #endregion
    }
}